package com.ssy.lingxi.member.merchant.serviceimpl.base;

import com.ssy.lingxi.common.exception.BusinessException;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.member.merchant.api.constant.MemberRelationTypeEnum;
import com.ssy.lingxi.member.merchant.config.ServiceConfig;
import com.ssy.lingxi.member.merchant.entity.*;
import com.ssy.lingxi.member.merchant.model.constant.*;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.MemberInnerHistoryVO;
import com.ssy.lingxi.member.merchant.model.vo.basic.response.MemberOuterHistoryVO;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.response.MemberAppraisalHistoryVO;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.response.MemberRectifyInnerHistoryVO;
import com.ssy.lingxi.member.merchant.model.vo.lifecycle.response.MemberRectifyOuterHistoryVO;
import com.ssy.lingxi.member.merchant.model.vo.maintenance.response.MemberDepositDetailHistoryVO;
import com.ssy.lingxi.member.merchant.repository.*;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberHistoryService;
import com.ssy.lingxi.member.merchant.utils.NumberUtil;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 会员历史记录基础服务接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2021-05-20
 */
@Service
public class BaseMemberHistoryServiceImpl implements IBaseMemberHistoryService {
    @Resource
    private MemberValidateHistoryRepository memberValidateHistoryRepository;

    @Resource
    private MemberInnerValidateHistoryRepository memberInnerValidateHistoryRepository;

    @Resource
    private MemberDepositoryDetailHistoryRepository memberDepositoryDetailHistoryRepository;

    @Resource
    private MemberAppraisalHistoryRepository memberAppraisalHistoryRepository;

    @Resource
    private MemberRectifyOuterHistoryRepository memberRectifyOuterHistoryRepository;

    @Resource
    private MemberRectifyInnerHistoryRepository memberRectifyInnerHistoryRepository;


    /**
     * 查询外部单据流转记录
     *
     * @param relationDO 会员关系
     * @return 查询结果
     */
    @Override
    public List<MemberOuterHistoryVO> listMemberOuterHistory(MemberRelationDO relationDO) {
        return listMemberOuterHistory(relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getSubMemberId(), relationDO.getSubRoleId());
    }

    /**
     * 查询外部单据流转记录
     *
     * @param memberId    上级会员Id
     * @param roleId      上级会角色Id
     * @param subMemberId 下级会员Id
     * @param subRoleId   下级会员角色Id
     * @return 查询结果
     */
    @Override
    public List<MemberOuterHistoryVO> listMemberOuterHistory(Long memberId, Long roleId, Long subMemberId, Long subRoleId) {
        return memberValidateHistoryRepository.findAllByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(memberId, roleId, subMemberId, subRoleId, Sort.by("id").descending()).stream().map(h -> {
            MemberOuterHistoryVO historyVO = new MemberOuterHistoryVO();
            historyVO.setId(h.getId());
            historyVO.setCreateTime(h.getCreateTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
            historyVO.setOuterStatus(h.getOuterStatus());
            historyVO.setOuterStatusName(MemberOuterStatusEnum.getCodeMsg(h.getOuterStatus()));
            historyVO.setOperation(NumberUtil.isNullOrZero(h.getOperationCode()) ? h.getOperation() : MemberValidateHistoryOperationEnum.getMsgByCode(h.getOperationCode()));
            historyVO.setOperatorRoleName(h.getOperatorRoleName());
            historyVO.setRemark(h.getRemark());
            return historyVO;
        }).collect(Collectors.toList());
    }

    /**
     * 查询内部单据流转记录
     *
     * @param relationDO 会员关系
     * @return 查询结果
     */
    @Override
    public List<MemberInnerHistoryVO> listMemberInnerHistory(MemberRelationDO relationDO) {
        return listMemberInnerHistory(relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getSubMemberId(), relationDO.getSubRoleId());
    }

    /**
     * 查询内部单据流转记录
     *
     * @param memberId    上级会员Id
     * @param roleId      上级会角色Id
     * @param subMemberId 下级会员Id
     * @param subRoleId   下级会员角色Id
     * @return 查询结果
     */
    @Override
    public List<MemberInnerHistoryVO> listMemberInnerHistory(Long memberId, Long roleId, Long subMemberId, Long subRoleId) {
        return memberInnerValidateHistoryRepository.findByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(memberId, roleId, subMemberId, subRoleId, Sort.by("id").descending()).stream().map(h -> {
            MemberInnerHistoryVO historyVO = new MemberInnerHistoryVO();
            historyVO.setId(h.getId());
            historyVO.setCreateTime(h.getCreateTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
            historyVO.setOperatorName(h.getOperatorName());
            historyVO.setOperatorOrgName(h.getOperatorOrgName());
            historyVO.setOperatorJobTitle(h.getOperatorJobTitle());
            historyVO.setOperation(NumberUtil.isNullOrZero(h.getOperateCode()) ? h.getOperation() : MemberValidateHistoryOperationEnum.getMsgByCode(h.getOperateCode()));
            historyVO.setInnerStatus(h.getInnerStatus());
            historyVO.setInnerStatusName(h.getRelType().equals(MemberRelationTypeEnum.PLATFORM.getCode()) ? PlatformInnerStatusEnum.getCodeMsg(h.getInnerStatus()) : MemberInnerStatusEnum.getCodeMsg(h.getInnerStatus()));
            historyVO.setRemark(h.getRemark());
            return historyVO;
        }).collect(Collectors.toList());
    }

    /**
     * 保存会员内部审核历史记录
     *
     * @param relationDO    会员关系
     * @param loginUser     登录用户
     * @param operationEnum 操作类型枚举
     * @param remark        备注信息
     */
    @Override
    public void saveMemberInnerHistory(MemberRelationDO relationDO, UserLoginCacheDTO loginUser, MemberValidateHistoryOperationEnum operationEnum, String remark) {
        MemberInnerValidateHistoryDO historyDO = new MemberInnerValidateHistoryDO();
        historyDO.setCreateTime(LocalDateTime.now());
        historyDO.setRelType(relationDO.getRelType());
        historyDO.setMemberId(relationDO.getMemberId());
        historyDO.setRoleId(relationDO.getRoleId());
        historyDO.setMemberName(relationDO.getMember().getName());
        historyDO.setRoleName(relationDO.getRole().getRoleName());
        historyDO.setSubMemberId(relationDO.getSubMemberId());
        historyDO.setSubRoleId(relationDO.getSubRoleId());
        historyDO.setRelType(relationDO.getRelType());
        historyDO.setOperatorId(loginUser.getUserId());
        historyDO.setOperatorName(loginUser.getUserName());
        historyDO.setOperatorRoleName(loginUser.getUserRoleName());
        historyDO.setOperatorOrgName(loginUser.getUserOrgName());
        historyDO.setOperatorJobTitle(loginUser.getUserJobTitle());
        historyDO.setOperateCode(operationEnum.getCode());
        historyDO.setOperation(operationEnum.getMsg());
        historyDO.setInnerStatus(relationDO.getInnerStatus());
        historyDO.setOuterStatus(relationDO.getOuterStatus());
        historyDO.setStatus(relationDO.getStatus());
        historyDO.setRemark(StringUtils.hasLength(remark) ? remark : "");
        memberInnerValidateHistoryRepository.saveAndFlush(historyDO);
    }

    /**
     * 保存会员外部审核历史记录
     * @param relationDO  会员关系
     * @param operationEnum 操作方法枚举
     * @param remark 备注信息
     */
    @Override
    public void saveMemberOuterHistory(MemberRelationDO relationDO, MemberValidateHistoryOperationEnum operationEnum, String remark) {
        saveMemberOuterHistory(relationDO, relationDO.getRole().getRoleName(), operationEnum, MemberOuterStatusEnum.getCodeMsg(relationDO.getOuterStatus()), remark);
    }

    /**
     * 保存会员外部审核历史记录
     *
     * @param relationDO 会员关系
     * @param operationEnum  操作方法枚举
     * @param outerStatusName 指定状态名称
     * @param remark     备注信息
     */
    @Override
    public void saveMemberOuterHistory(MemberRelationDO relationDO, String operatorRoleName, MemberValidateHistoryOperationEnum operationEnum, String outerStatusName, String remark) {
        MemberValidateHistoryDO historyDO = new MemberValidateHistoryDO();
        historyDO.setCreateTime(LocalDateTime.now());
        historyDO.setMemberId(relationDO.getMemberId());
        historyDO.setMemberName(relationDO.getMember().getName());
        historyDO.setRoleId(relationDO.getRoleId());
        historyDO.setRoleName(relationDO.getRole().getRoleName());
        historyDO.setSubMemberId(relationDO.getSubMemberId());
        historyDO.setSubMemberName(relationDO.getSubMember().getName());
        historyDO.setRelType(relationDO.getRelType());
        historyDO.setSubRoleId(relationDO.getSubRoleId());
        historyDO.setSubRoleName(relationDO.getSubRoleName());
        historyDO.setOuterStatus(relationDO.getOuterStatus());
        historyDO.setOperatorRoleName(operatorRoleName);
        historyDO.setOperationCode(operationEnum.getCode());
        historyDO.setOperation(operationEnum.getMsg());
        historyDO.setRemark(StringUtils.hasLength(remark) ? remark.trim() : "");
        memberValidateHistoryRepository.saveAndFlush(historyDO);
    }

    /**
     * 分页查询会员入库资料历史记录
     *
     * @param relationDO 会员关系
     * @param current   当前页
     * @param pageSize  每页行数
     * @return 查询结果
     */
    @Override
    public PageData<MemberDepositDetailHistoryVO> pageMemberDepositDetailHistory(MemberRelationDO relationDO, int current, int pageSize) {
        Pageable pageable = PageRequest.of(current - 1, pageSize, Sort.by("id").descending());
        Page<MemberDepositoryDetailHistoryDO> pageList = memberDepositoryDetailHistoryRepository.findByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(relationDO.getMemberId(), relationDO.getRoleId(), relationDO.getSubMemberId(), relationDO.getSubRoleId(), pageable);
        return new PageData<>(pageList.getTotalElements(), pageList.getContent().stream().map(historyDO -> {
            MemberDepositDetailHistoryVO historyVO = new MemberDepositDetailHistoryVO();
            historyVO.setId(historyDO.getId());
            historyVO.setCreateTime(historyDO.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
            historyVO.setFieldLocalName(historyDO.getFieldLocalName());
            historyVO.setFieldValue(historyDO.getFieldValue());
            historyVO.setLastValue(historyDO.getLastValue());
            return historyVO;
        }).collect(Collectors.toList()));
    }

    /**
     * 更改内部、外部历史记录的下级会员Id
     *
     * @param subMemberId  下级会员Id
     * @param oldSubRoleId 旧的下级会员角色Id
     * @param newSubRoleId 新的下级会员角色Id
     * @param newSubRoleName 新的下级会员角色名称
     * @param newSubMemberName 新的下级会员名称
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public void updateHistorySubRoleId(Long subMemberId, Long oldSubRoleId, Long newSubRoleId, String newSubRoleName, String newSubMemberName) {
        //更改内部审核记录
        List<MemberInnerValidateHistoryDO> innerHistory = memberInnerValidateHistoryRepository.findBySubMemberIdAndSubRoleId(subMemberId, oldSubRoleId);
        if (!CollectionUtils.isEmpty(innerHistory)) {
            innerHistory.forEach(h -> h.setSubRoleId(newSubRoleId));
            memberInnerValidateHistoryRepository.saveAll(innerHistory);
        }

        //更改外部审核记录
        List<MemberValidateHistoryDO> outerHistory = memberValidateHistoryRepository.findBySubMemberIdAndSubRoleId(subMemberId, oldSubRoleId);
        if (!CollectionUtils.isEmpty(outerHistory)) {
            outerHistory.forEach(h -> {
                h.setSubMemberName(newSubMemberName);
                h.setSubRoleId(newSubRoleId);
                h.setSubRoleName(newSubRoleName);
            });
            memberValidateHistoryRepository.saveAll(outerHistory);
        }
    }

    /**
     * 删除下级会员的内、外历史记录
     *
     * @param subMemberId 下级会员Id
     * @param subRoleId   下级会员角色Id
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public void deleteHistoryBySubMemberIdAndSubRoleId(Long subMemberId, Long subRoleId) {
        memberValidateHistoryRepository.deleteAllBySubMemberIdAndSubRoleId(subMemberId, subRoleId);
        memberInnerValidateHistoryRepository.deleteAllBySubMemberIdAndSubRoleId(subMemberId, subRoleId);
    }

    /**
     * 删除会员关系时，删除下级会员的内、外历史记录
     *
     * @param memberId    上级会员Id
     * @param roleId      上级会员角色Id
     * @param subMemberId 下级会员Id
     * @param subRoleId   下级会员角色Id
     */
    @Transactional(rollbackFor = BusinessException.class)
    @Override
    public void deleteHistoryByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(Long memberId, Long roleId, Long subMemberId, Long subRoleId) {
        memberValidateHistoryRepository.deleteByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(memberId, roleId, subMemberId, subRoleId);
        memberInnerValidateHistoryRepository.deleteByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(memberId, roleId, subMemberId, subRoleId);
    }

    /**
     * 保存会员考评历史记录
     *  @param loginUser 登录用户
     * @param appraisalId 考评id
     * @param status 状态
     * @param statusName 状态名称
     * @param operation  操作说明
     * @param remark     备注信息
     */
    @Override
    public void saveMemberAppraisalHistory(UserLoginCacheDTO loginUser, Long appraisalId, Integer status, String statusName, String operation, String remark) {
        MemberAppraisalHistoryDO historyDO = new MemberAppraisalHistoryDO();
        historyDO.setAppraisalId(appraisalId);
        historyDO.setOperatorName(loginUser.getUserName());
        historyDO.setOperatorRoleName(loginUser.getUserRoleName());
        historyDO.setOperatorOrgName(loginUser.getUserOrgName());
        historyDO.setOperatorJobTitle(loginUser.getUserJobTitle());
        historyDO.setOperation(operation);
        historyDO.setCreateTime(LocalDateTime.now());
        historyDO.setRemark(remark);
        historyDO.setOperation(operation);
        historyDO.setStatus(status);
        historyDO.setStatusName(statusName);
        historyDO.setRemark(StringUtils.hasLength(remark) ? remark.trim() : "");

        memberAppraisalHistoryRepository.saveAndFlush(historyDO);
    }

    /**
     * 查询会员考评单据流转记录
     *
     * @param appraisalId   考评id
     * @return 查询结果
     */
    @Override
    public List<MemberAppraisalHistoryVO> listMemberAppraisalHistory(Long appraisalId) {
        return memberAppraisalHistoryRepository.findByAppraisalId(appraisalId, Sort.by("id").descending()).stream().map(h -> {
            MemberAppraisalHistoryVO historyVO = new MemberAppraisalHistoryVO();
            historyVO.setId(h.getId());
            historyVO.setCreateTime(h.getCreateTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
            historyVO.setOperatorName(h.getOperatorName());
            historyVO.setOperatorOrgName(h.getOperatorOrgName());
            historyVO.setOperatorJobTitle(h.getOperatorJobTitle());
            historyVO.setOperation(h.getOperation());
            historyVO.setStatus(h.getStatus());
            historyVO.setStatusName(h.getStatusName());
            historyVO.setRemark(h.getRemark());
            return historyVO;
        }).collect(Collectors.toList());
    }

    @Override
    public void saveMemberRectifyOuterHistory(UserLoginCacheDTO loginUser, Long rectifyId, Long subMemberId, Long subRoleId, Integer outerStatus, String operation, String remark) {
        MemberRectifyOuterHistoryDO historyDO = new MemberRectifyOuterHistoryDO();
        historyDO.setRectifyId(rectifyId);
        historyDO.setCreateTime(LocalDateTime.now());
        historyDO.setMemberId(subMemberId);
        historyDO.setMemberName(loginUser.getCompany());
        historyDO.setRoleId(subRoleId);
        historyDO.setRoleName(loginUser.getMemberRoleName());
        historyDO.setSubMemberId(subMemberId);
        historyDO.setSubRoleId(subRoleId);
        historyDO.setInnerStatus(outerStatus);
        historyDO.setOuterStatus(outerStatus);
        historyDO.setInnerStatusName(MemberRectifyStatusEnum.getCodeMessage(outerStatus));
        historyDO.setOuterStatusName(MemberRectifyStatusEnum.getCodeMessage(outerStatus));

        historyDO.setOperation(operation);
        historyDO.setRemark(StringUtils.hasLength(remark) ? remark.trim() : "");

        memberRectifyOuterHistoryRepository.saveAndFlush(historyDO);
    }

    @Override
    public void saveMemberRectifyInnerHistory(UserLoginCacheDTO loginUser, Long rectifyId,Long subMemberId, Long subRoleId, Integer outerStatus, String operation, String remark) {
        MemberRectifyInnerHistoryDO historyDO = new MemberRectifyInnerHistoryDO();
        historyDO.setRectifyId(rectifyId);
        historyDO.setCreateTime(LocalDateTime.now());
        historyDO.setMemberId(loginUser.getMemberId());
        historyDO.setMemberName(loginUser.getCompany());
        historyDO.setRoleId(loginUser.getMemberRoleId());
        historyDO.setRoleName(loginUser.getMemberRoleName());
        historyDO.setSubMemberId(subMemberId);
        historyDO.setSubRoleId(subRoleId);
        historyDO.setOperatorName(loginUser.getUserName());
        historyDO.setOperatorRoleName(loginUser.getUserRoleName());
        historyDO.setOperatorOrgName(loginUser.getUserOrgName());
        historyDO.setOperatorJobTitle(loginUser.getUserJobTitle());
        historyDO.setInnerStatus(outerStatus);
        historyDO.setOuterStatus(outerStatus);
        historyDO.setInnerStatusName(MemberRectifyStatusEnum.getCodeMessage(outerStatus));
        historyDO.setOuterStatusName(MemberRectifyStatusEnum.getCodeMessage(outerStatus));
        historyDO.setOperation(operation);
        historyDO.setRemark(StringUtils.hasLength(remark) ? remark.trim() : "");
        memberRectifyInnerHistoryRepository.saveAndFlush(historyDO);
    }

    @Override
    public List<MemberRectifyOuterHistoryVO> listMemberRectifyOuterHistory(Long rectifyId) {
        return memberRectifyOuterHistoryRepository.findByRectifyId(rectifyId, Sort.by("id").descending()).stream().map(h -> {
            MemberRectifyOuterHistoryVO historyVO = new MemberRectifyOuterHistoryVO();
            historyVO.setId(h.getId());
            historyVO.setCreateTime(h.getCreateTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
            historyVO.setOuterStatus(h.getOuterStatus());
            historyVO.setOuterStatusName(h.getOuterStatusName());
            historyVO.setOperation(h.getOperation());
            historyVO.setOperatorRoleName(h.getRoleName());
            historyVO.setRemark(h.getRemark());
            return historyVO;
        }).collect(Collectors.toList());
    }

    @Override
    public List<MemberRectifyInnerHistoryVO> listMemberRectifyInnerHistory(Long rectifyId) {
        return memberRectifyInnerHistoryRepository.findByRectifyId(rectifyId, Sort.by("id").descending()).stream().map(h -> {
            MemberRectifyInnerHistoryVO historyVO = new MemberRectifyInnerHistoryVO();
            historyVO.setId(h.getId());
            historyVO.setCreateTime(h.getCreateTime().format(ServiceConfig.DEFAULT_DATETIME_FORMATTER));
            historyVO.setOperatorName(h.getOperatorName());
            historyVO.setOperatorOrgName(h.getOperatorOrgName());
            historyVO.setOperatorJobTitle(h.getOperatorJobTitle());
            historyVO.setOperation(h.getOperation());
            historyVO.setInnerStatus(h.getInnerStatus());
            historyVO.setInnerStatusName(h.getInnerStatusName());
            historyVO.setRemark(h.getRemark());
            return historyVO;
        }).collect(Collectors.toList());
    }
}
